package com.finger.gulimall.ware.service.impl;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.finger.common.constant.MqStockConstant;
import com.finger.common.to.SkuHasStockTO;
import com.finger.common.utils.PageUtils;
import com.finger.common.utils.Query;
import com.finger.common.utils.R;
import com.finger.gulimall.ware.dao.WareSkuDao;
import com.finger.gulimall.ware.entity.WareOrderTaskDetailEntity;
import com.finger.gulimall.ware.entity.WareOrderTaskEntity;
import com.finger.gulimall.ware.entity.WareSkuEntity;
import com.finger.gulimall.ware.entity.to.OrderTo;
import com.finger.gulimall.ware.exception.NotStockException;
import com.finger.gulimall.ware.feign.OrderRemoteService;
import com.finger.gulimall.ware.feign.ProductRemoteService;
import com.finger.gulimall.ware.service.WareOrderTaskDetailService;
import com.finger.gulimall.ware.service.WareOrderTaskService;
import com.finger.gulimall.ware.service.WareSkuService;
import com.finger.gulimall.ware.entity.to.LockStockTo;
import com.finger.gulimall.ware.entity.to.MqLockStockTo;
import com.finger.gulimall.ware.entity.vo.OrderVo;
import com.finger.gulimall.ware.entity.vo.WareSkuLockVo;
import lombok.extern.log4j.Log4j2;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;


@Log4j2
@Service("wareSkuService")
public class WareSkuServiceImpl extends ServiceImpl<WareSkuDao, WareSkuEntity> implements WareSkuService {

	@Autowired
	private ProductRemoteService productRemoteService;

	@Autowired
	WareOrderTaskService wareOrderTaskService;

	@Autowired
	WareOrderTaskDetailService wareOrderTaskDetailService;

	@Autowired
	RabbitTemplate rabbitTemplate;

	@Autowired
	OrderRemoteService orderRemoteService;

	@Override
	public PageUtils queryPage(Map<String, Object> params) {

        /*
            page: 1
            limit: 10
            skuId:
            wareId:
         */
		QueryWrapper<WareSkuEntity> queryWrapper = new QueryWrapper<>();

		String skuId = (String) params.get("skuId");
		String wareId = (String) params.get("wareId");

		if (!StringUtils.isEmpty(skuId)) {
			queryWrapper.eq("sku_id", skuId);
		}

		if (!StringUtils.isEmpty(wareId)) {
			queryWrapper.eq("ware_id", wareId);
		}

		IPage<WareSkuEntity> page = this.page(new Query<WareSkuEntity>().getPage(params), queryWrapper);

		return new PageUtils(page);
	}

	@Override
	public void addStock(Long wareId, Long skuId, Integer skuNum) {
		// 根据skuid和仓库id查询该商品是否存在
		QueryWrapper<WareSkuEntity> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("sku_id", skuId).eq("ware_id", wareId);
		WareSkuEntity wareSkuEntity = baseMapper.selectOne(queryWrapper);

		// 如果该商品存在
		if (wareSkuEntity != null) {
			// 更新该商品数量
			Integer stock = wareSkuEntity.getStock();
			wareSkuEntity.setStock(stock + skuNum);
			this.baseMapper.updateById(wareSkuEntity);
		} else {
			// 如果该商品不存在，创键一个该商品实体，查询
			wareSkuEntity = new WareSkuEntity();
			wareSkuEntity.setSkuId(skuId);
			try {

				// TODO 远程获取商品名字
				R result = productRemoteService.getSkuName(skuId);
				if (result.getCode() == 0) {
					wareSkuEntity.setSkuName((String) result.get("skuName"));
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
			wareSkuEntity.setStockLocked(0);
			wareSkuEntity.setWareId(wareId);
			wareSkuEntity.setStock(skuNum);
			baseMapper.insert(wareSkuEntity);
		}
	}

	@Override
	public List<SkuHasStockTO> queryHasStock(List<Long> skuIds) {
		// 根据skuid 查出该商品的库存数量。并创建相应的TO 收集成集合，返回
		return skuIds.stream().map(skuid -> {
			Long stockCount = baseMapper.queryHasStock(skuid);
			SkuHasStockTO skuHasStockTo = new SkuHasStockTO();
			skuHasStockTo.setSkuId(skuid);
			skuHasStockTo.setHasStock(stockCount != null && stockCount > 0);
			return skuHasStockTo;
		}).collect(Collectors.toList());
	}

	@Transactional
	@Override
	public Boolean lockStock(WareSkuLockVo wareSkuLockVo) {

		String orderSn = wareSkuLockVo.getOrderSn();

		WareOrderTaskEntity taskEntity = new WareOrderTaskEntity();
		taskEntity.setOrderSn(orderSn);
		wareOrderTaskService.save(taskEntity);

		List<LockStockTo> lockStocks = wareSkuLockVo.getLockStockTos().stream().map(item -> {
			Long skuId = item.getSkuId();
			QueryWrapper<WareSkuEntity> queryWrapper = new QueryWrapper<>();
			queryWrapper.eq("sku_id", skuId).select("ware_id");

			// 查出当前sku有哪些仓库
			List<Object> wareIds = baseMapper.selectObjs(queryWrapper);
			LockStockTo lockStockTo = new LockStockTo();
			lockStockTo.setNum(item.getNum());
			lockStockTo.setSkuId(skuId);
			lockStockTo.setWareIds(wareIds);
			return lockStockTo;
		}).collect(Collectors.toList());

		for (LockStockTo lockStock : lockStocks) {

			boolean locked = false;

			Long skuId = lockStock.getSkuId();
			List<Object> wareIds = lockStock.getWareIds();
			if (wareIds != null && wareIds.size() > 0) {
				// 商品有仓库
				for (Object wareIdObj : wareIds) {
					Long wareId = (Long) wareIdObj;
					Long resRows = this.baseMapper.lockStock(skuId, wareId, lockStock.getNum(), lockStock.getNum());
					if (resRows > 0) {
						// 锁定成功
						locked = true;
						WareOrderTaskDetailEntity taskDetailEntity = new WareOrderTaskDetailEntity(null, skuId, "", lockStock.getNum(), taskEntity.getId(), wareId, 1);
						wareOrderTaskDetailService.save(taskDetailEntity);
						MqLockStockTo mqLockStockTo = new MqLockStockTo();
						BeanUtils.copyProperties(taskDetailEntity, mqLockStockTo);
						mqLockStockTo.setOrderSn(orderSn);
						rabbitTemplate.convertAndSend(MqStockConstant.STOCK_EVENT_EXCHANGE, MqStockConstant.STOCK_DELAY_QUEUE, mqLockStockTo);
						break;
					}

				}

				if (!locked) {
					// 所有仓库都没锁上库存
					throw new NotStockException("商品id：" + skuId + "，没有库存");
				}

			} else {
				// 商品没有仓库，就说明没有库存
				throw new NotStockException("商品id：" + skuId + "，没有库存");
			}

		}

		return true;

	}

	/**
	 * 解锁库存
	 * @param stockTo
	 */
	@Override
	public void unLockStock(MqLockStockTo stockTo) {
		Long id = stockTo.getId();
		WareOrderTaskDetailEntity detailEntity = wareOrderTaskDetailService.getById(id);
		// 库存工作单详情不为空并且锁定状态为已锁定才会进入解锁库存逻辑
		if (detailEntity != null && detailEntity.getLockStatus() == 1) {
			R r = orderRemoteService.getOrderByOrderSn(stockTo.getOrderSn());
			if (r.getCode() == 0) {
				OrderVo orderVo = r.getData(new TypeReference<OrderVo>() {
				});
				// 订单为空说明订单服务出错回滚，订单状态为4说明订单取消，两种情况库存都需要解锁
				if (orderVo == null || orderVo.getStatus() == 4) {
					// 解锁库存
					log.info("库存解锁：" + stockTo.getSkuId() + ":" + stockTo.getWareId() + ":" + stockTo.getSkuNum());
					baseMapper.unLockStock(stockTo.getSkuId(), stockTo.getWareId(), stockTo.getSkuNum());
					// 将库存工作单扣减状态改为已扣减
					WareOrderTaskDetailEntity entity = new WareOrderTaskDetailEntity();
					entity.setId(stockTo.getId());
					entity.setLockStatus(2);
					wareOrderTaskDetailService.updateById(entity);
				}
			}
		}
	}

	/**
	 * 订单时间到主动触发关单并触发解锁库存逻辑
	 * @param orderTo
	 */
	@Transactional(rollbackFor = Exception.class)
	@Override
	public void unLockStock(OrderTo orderTo) {
		String orderSn = orderTo.getOrderSn();
		WareOrderTaskEntity taskEntity = wareOrderTaskService.getByOrderSn(orderSn);
		if (taskEntity != null) {
			Long taskId = taskEntity.getId();
			List<WareOrderTaskDetailEntity> list = wareOrderTaskDetailService.list(new LambdaQueryWrapper<WareOrderTaskDetailEntity>().eq(WareOrderTaskDetailEntity::getTaskId, taskId));
			List<WareOrderTaskDetailEntity> collect = list.stream().filter(e -> e.getLockStatus() == 1).collect(Collectors.toList());
			// 如果工作单下的详细项有一个锁定状态为1
			if(collect.size() > 0) {
				for (WareOrderTaskDetailEntity e : list) {
					e.setLockStatus(2);
					baseMapper.unLockStock(e.getSkuId(),e.getWareId(),e.getSkuNum());
				}
				// 修改工作单详情锁定状态
				wareOrderTaskDetailService.updateBatchById(list);

			}
		}
	}
}